var RDFaInAction = RDFaInAction || {};
(function() {

function ImageAnnotator() {
   this.documents = {};
   this.alwaysShow = false;
}

ImageAnnotator.prototype._findPos = function(obj) {
   var curleft = curtop = 0;
   for (var node = obj; node; node=node.offsetParent) { 
      curleft += node.offsetLeft;
      curtop += node.offsetTop;
   }
   return [curleft,curtop];
}
ImageAnnotator.prototype.process = function(doc,baseURI) {
   var context = {};
   context.document = doc;
   this.documents[baseURI ? baseURI : doc.baseURI] = context;
   this.update(context);
}

ImageAnnotator.prototype.update = function(context) {
   context.targets = context.document.getElementsByType("http://schema.org/ImageObject");
   context.annotatedSubjects = {};
   var app = this;
   var makeHandler = function(target) {
      return function() {
         app.updateImage(context,target,target.data.id);
      };
   };
   for (var i=0; i<context.targets.length; i++) {
      var target = context.targets[i];
      if (target.localName!="img") {
         continue;
      }
      if (target.complete) {
         this.updateImage(context,target,target.data.id);
      } else {
         target.addEventListener("load",makeHandler(target),false);
      }
   }
}

ImageAnnotator.prototype.updateImage = function(context,img,subject) {
   var annotatedSubject = context.annotatedSubjects[subject];
   if (!annotatedSubject) {
      annotatedSubject = {}
      annotatedSubject.canvas = context.document.createElement("canvas");
      annotatedSubject.canvas.setAttribute("height",img.height);
      annotatedSubject.canvas.setAttribute("width",img.width);
      annotatedSubject.img = img;
      var imgPos = this._findPos(img);
      img.parentNode.insertBefore(annotatedSubject.canvas,img);
      annotatedSubject.c2d = annotatedSubject.canvas.getContext("2d");
      annotatedSubject.canvas.style.position = "absolute";
      annotatedSubject.canvas.style.left = imgPos[0];
      annotatedSubject.canvas.style.top = imgPos[1];
      context.annotatedSubjects[subject] = annotatedSubject;
   }
   var annotations = context.document.data.getValues(subject,"http://schema.org/annotation");
   for (var i=0; i<annotations.length; i++) {
      if (context.document.data.getValues(annotations[i],"rdf:type").indexOf("http://schema.org/Comment")>=0) {
         console.log("Annotation: "+annotations[i]);
         this.applyBoxImageAnnotation(context,annotatedSubject,annotations[i]);
      } else {
         console.log("Unknown annotation type: "+type);
      }
   }
}

ImageAnnotator.prototype.applyBoxImageAnnotation = function(context,annotatedSubject,annotationSubject) {
   var annotationElement = context.document.getElementsBySubject(annotationSubject)[0];
   var regions = context.document.data.getValues(annotationSubject,"http://schema.org/region");
   if (regions.length==0) {
      return;
   }
   // only use the first one
   // TODO: enable more than one region
   var region = regions[0];
   var regionElement = context.document.getElementsBySubject(regions[0])[0];
   if (context.document.data.getValues(region,"rdf:type").indexOf("http://schema.org/Rectangle")<0) {
      return;
   }
   var x = parseInt(context.document.data.getValues(region,"http://schema.org/positionX")[0]);
   var y = parseInt(context.document.data.getValues(region,"http://schema.org/positionY")[0]);
   var width = parseInt(context.document.data.getValues(region,"http://schema.org/width")[0]);
   var height = parseInt(context.document.data.getValues(region,"http://schema.org/height")[0]);
   var lineColor = context.document.defaultView.getComputedStyle(regionElement).color;
   var lineWidth = 2;
   
   var hotRegion = {
      left: annotatedSubject.canvas.offsetLeft+x, right: annotatedSubject.canvas.offsetLeft+x+width,
      top: annotatedSubject.canvas.offsetTop+y, bottom: annotatedSubject.canvas.offsetTop+y+height
   };
   if (this.alwaysShow) {
      annotatedSubject.c2d.strokeStyle = lineColor;
      annotatedSubject.c2d.lineWidth = lineWidth;
      annotatedSubject.c2d.beginPath();
      annotatedSubject.c2d.moveTo(x,y);
      annotatedSubject.c2d.lineTo(x+width,y);
      annotatedSubject.c2d.lineTo(x+width,y+height);
      annotatedSubject.c2d.lineTo(x,y+height);
      annotatedSubject.c2d.lineTo(x,y);
      annotatedSubject.c2d.stroke();
   } else {
      var on = false;
      annotatedSubject.canvas.addEventListener("mousemove",function(e) {
         if (e.pageX>=hotRegion.left && e.pageX<=hotRegion.right && e.pageY>=hotRegion.top && e.pageY<=hotRegion.bottom) {
            if (!on) {
               annotatedSubject.c2d.strokeStyle = lineColor;
               annotatedSubject.c2d.lineWidth = lineWidth;
               annotatedSubject.c2d.beginPath();
               annotatedSubject.c2d.moveTo(x,y);
               annotatedSubject.c2d.lineTo(x+width,y);
               annotatedSubject.c2d.lineTo(x+width,y+height);
               annotatedSubject.c2d.lineTo(x,y+height);
               annotatedSubject.c2d.lineTo(x,y);
               annotatedSubject.c2d.stroke();
            }
            on = true;
         } else {
            if (on) {
               annotatedSubject.c2d.clearRect(x-lineWidth,y-lineWidth,x+width,y+height);
               on = false;
            }
         }
      },false);
   }
   var descriptions = context.document.data.getValueOrigins(annotationSubject,"http://schema.org/description");
   var texts = context.document.data.getValueOrigins(annotationSubject,"http://schema.org/text");
   if (descriptions.length>0) {
       this.addToolTip(
          annotatedSubject.canvas,
          { title: { value: descriptions[0].value, 
                     style: descriptions[0].origin.style,
                     computedStyle: context.document.defaultView.getComputedStyle(descriptions[0].origin) 
                    },
            text: texts.length>0 ? { value: texts[0].value, 
                                     style: texts[0].origin.style,
                                     computedStyle: context.document.defaultView.getComputedStyle(texts[0].origin) } 
                                 : null 
          },x,y,width,height
       );
   }
   var links = context.document.data.getValues(annotationSubject,"http://schema.org/url");
   if (links.length>0) {
      this.addLink(annotatedSubject.canvas,links[0],x,y,width,height);
   }
}

ImageAnnotator.prototype.copyStyle = function(target,source) {
   target.style.color = source.computedStyle.color;
   target.style.backgroundColor = source.computedStyle.backgroundColor;
   target.style.paddingLeft = source.computedStyle.paddingLeft;
   target.style.paddingRight = source.computedStyle.paddingRight;
   target.style.paddingTop = source.computedStyle.paddingTop;
   target.style.paddingBottom = source.computedStyle.paddingBottom;
   target.style.marginLeft = source.computedStyle.marginLeft;
   target.style.marginRight = source.computedStyle.marginRight;
   target.style.marginTop = source.computedStyle.marginTop;
   target.style.marginBottom = source.computedStyle.marginBottom;
   target.style.fontFamily = source.computedStyle.fontFamily;
   target.style.fontSize = source.computedStyle.fontSize;
   target.style.fontSizeAdjust = source.computedStyle.fontSizeAdjust;
   target.style.fontVariant = source.computedStyle.fontVariant;
   target.style.fontWeight = source.computedStyle.fontWeight;
   target.style.width = source.style.width;
   target.style.height = source.style.height;
   target.style.overflow = source.computedStyle.overflow;
   target.style.minWidth = source.computedStyle.minWidth;
   target.style.maxWidth = source.computedStyle.maxWidth;
}

ImageAnnotator.prototype.addToolTip = function(element,tip,x,y,width,height) {
   console.log("Adding tip: "+tip.title.value);
   var region = {
      left: element.offsetLeft+x, right: element.offsetLeft+x+width,
      top: element.offsetTop+y, bottom: element.offsetTop+y+height
   };
   var timer = null;
   var tooltip = element.ownerDocument.createElement("div");
   element.parentNode.insertBefore(tooltip,element);
   tooltip.className = "tooltip";
   tooltip.style.display = "none";
   tooltip.style.position = "absolute";
   var titleContainer = element.ownerDocument.createElement("div");
   tooltip.appendChild(titleContainer);
   titleContainer.appendChild(element.ownerDocument.createTextNode(tip.title.value));
   if (tip.title.style) {
      this.copyStyle(titleContainer,tip.title);
   }
   if (tip.text) {
      var textContainer = element.ownerDocument.createElement("div");
      tooltip.appendChild(textContainer);
      textContainer.appendChild(element.ownerDocument.createTextNode(tip.text.value));
      if (tip.text.style) {
         this.copyStyle(textContainer,tip.text);
      }
   }
   var app = this;
   element.addEventListener("mousemove",function(e) {
      if (timer) {
         tooltip.style.display = "none";
         clearTimeout(timer);
         timer = null;
      }
      //console.log(e.pageX+","+region.left+","+region.right);
      //console.log(e.pageY+","+region.top+","+region.bottom);
      if (e.pageX>=region.left && e.pageX<=region.right && e.pageY>=region.top && e.pageY<=region.bottom) {
         timer = setTimeout(function() {
            //console.log("Displaying tip: "+description);
            tooltip.style.display = "block";
            var elementPos = app._findPos(element);
            tooltip.style.left = (elementPos[0]+x)+"px";
            tooltip.style.top = (elementPos[1]+y-tooltip.clientHeight-3)+"px";
         },500);
      }
   },false);
}

ImageAnnotator.prototype.addLink = function(element,link,x,y,width,height) {
   console.log("Adding link: "+link);
   var region = {
      left: element.offsetLeft+x, right: element.offsetLeft+x+width,
      top: element.offsetTop+y, bottom: element.offsetTop+y+height
   };
   element.addEventListener("mousemove",function(e) {
      if (e.pageX>=region.left && e.pageX<=region.right && e.pageY>=region.top && e.pageY<=region.bottom) {
         element.style.cursor = "pointer";
      } else {
         element.style.cursor = "auto";
      }
   },false);
   element.addEventListener("click",function(e) {
      if (e.pageX>=region.left && e.pageX<=region.right && e.pageY>=region.top && e.pageY<=region.bottom) {
         window.open(link);
      }
   },false);
}

RDFaInAction.ImageAnnotator = ImageAnnotator;
RDFaInAction.services = RDFaInAction.services || {};
RDFaInAction.services["ImageAnnotator"] = { constructor: RDFaInAction.ImageAnnotator, method: "process" };

})();

